package io.github.jsp.lock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;

@Component
public class JobTriggerLock {
    
    private static final Logger logger = LoggerFactory.getLogger(JobTriggerLock.class);
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    private static final String INSERT_TRIGGER_LOCK_SQL = 
        "INSERT INTO sys_job_trigger_lock (job_id, lock_time, node_id) VALUES (?, ?, ?) " +
        "ON CONFLICT (job_id) DO UPDATE SET lock_time = EXCLUDED.lock_time, node_id = EXCLUDED.node_id " +
        "WHERE sys_job_trigger_lock.lock_time < ?";
    
    private static final String DELETE_TRIGGER_LOCK_SQL = 
        "DELETE FROM sys_job_trigger_lock WHERE job_id = ? AND node_id = ?";
    
    private static final String CLEAN_EXPIRED_TRIGGER_LOCK_SQL = 
        "DELETE FROM sys_job_trigger_lock WHERE lock_time < ?";
    
    public boolean tryLockJob(Integer jobId, String nodeId, long lockTimeoutMillis) {
        try {
            Timestamp currentTime = new Timestamp(System.currentTimeMillis());
            Timestamp expireThreshold = new Timestamp(System.currentTimeMillis() - lockTimeoutMillis);
            
            cleanExpiredJobLocks(lockTimeoutMillis);
            
            int result = jdbcTemplate.update(INSERT_TRIGGER_LOCK_SQL, 
                jobId, currentTime, nodeId, expireThreshold);
            
            if (result > 0) {
                logger.debug("Successfully acquired job trigger lock: jobId={}, nodeId={}", jobId, nodeId);
                return true;
            }
            
            logger.debug("Failed to acquire job trigger lock: jobId={}, nodeId={} (already locked by another node)", 
                jobId, nodeId);
            return false;
            
        } catch (Exception e) {
            logger.error("Error acquiring job trigger lock: jobId={}, nodeId={}", jobId, nodeId, e);
            return false;
        }
    }
    
    public boolean unlockJob(Integer jobId, String nodeId) {
        try {
            int result = jdbcTemplate.update(DELETE_TRIGGER_LOCK_SQL, jobId, nodeId);
            
            if (result > 0) {
                logger.debug("Successfully released job trigger lock: jobId={}, nodeId={}", jobId, nodeId);
                return true;
            } else {
                logger.warn("Failed to release job trigger lock: jobId={}, nodeId={} (not found or different node)", 
                    jobId, nodeId);
                return false;
            }
        } catch (Exception e) {
            logger.error("Error releasing job trigger lock: jobId={}, nodeId={}", jobId, nodeId, e);
            return false;
        }
    }
    
    private void cleanExpiredJobLocks(long lockTimeoutMillis) {
        try {
            Timestamp expireThreshold = new Timestamp(System.currentTimeMillis() - lockTimeoutMillis);
            int cleanedCount = jdbcTemplate.update(CLEAN_EXPIRED_TRIGGER_LOCK_SQL, expireThreshold);
            
            if (cleanedCount > 0) {
                logger.debug("Cleaned {} expired job trigger locks", cleanedCount);
            }
        } catch (Exception e) {
            logger.warn("Error cleaning expired job trigger locks", e);
        }
    }
}